I would like to introduce this opening section by asserting that this project can be more easily implemented using a higher level language like Java or python. However my objective was to become more proficient in the use of C++, so I chose that language. It is also no harm to have some experience in writing code that would be similar to code written in higher languages libraries eg. as for the functions CheckifDateIsValid() or CheckIfYearIsValid() from the header section below. I have here the Farm Animal Record and Accounting software project implementation files available for download. I used CodeBlocks cross platform IDE to program the project in C++. Provided are the header,.cpp files, in CodeBlocks format. I include the executable seperately. I also include the header and .cpp files in word files for those who use a different IDE and wish to copy and paste the code with ease. I should say at this point that the implementation code for users logging on or password access restrictions, I have commented out of the code, for ease of access.
Next I will include the class components of the header file with each class followed by an explanation section.
class FarmAnimal // To support instantiation of unique object for each farm animal.
{
private:
string Animalid; // Also used to prevent duplicate entries in container.
int InWeight;
int OutWeight;
int Cost;
int AvCostProcess;
string Sex;
string Breed;
string SupplierName;
string BoughtDate;
float RetailPricePerkg;
float GrossSaleprice;
string SellDate;
int SoldFlag; // So it can easily be determined whether sales data is present or not.
public:
void setAnimalid(bool setby=false,string id="0"); // To ensure members are initialized
void setInWeight(bool setby=false,int theInWeight=0); // and there are also times when it's
void setOutWeight(bool setby=false,int theOutWeight=0); // useful to fill members with valid
void setCost(bool setby=false,int cost=0); // but generic data when deleting a
void setAvCostProcess(bool setby=false,int AvCostProcess=0);// member or for testing purposes
void setSex(bool setby=false,string theSex="unfilled");
int setBreed( bool setby=false,string theBreed="unfilled");
int setSupplierName(bool setby=false,string suppname="unfilled");
void setBoughtDate(bool setby=false,string BDate="unfilled");
void setRetailPricePerkg(bool setby=false,float theRetailPriceperkg=0);
void setGrossSaleprice(bool setby=false,float GrossSaleprice=0);
void setSellDate(bool setby=false,string SDate="unfilled");
void setSoldFlag(int thesoldflag=0);
string getAnimalid();
int getInWeight();
int getOutWeight();
int getCost();
int getAvCostProcess();
string getSex();
string getBreed();
string getSupplierName();
string getBoughtDate();
float getRetailPricePerkg();
float getGrossSaleprice();
string getSellDate();
int getSoldFlag();
FarmAnimal& operator=(FarmAnimal& RHS); // Overloading the equals operator means each
bool operator==(FarmAnimal& RHS); // member can be compared easily.Other programs
// maybe written utilizing this class
// where it would be important to have use of these
// overloaded operators.
bool CheckIfYearIsValid(string Year); // These functions will ensure integrity and
bool CheckIfStringIsValid(string name); // correct format of data before committing
bool CheckIfDateIsValid(string Date); // it to the data structure.
bool CheckIfAnimalIdIsValid(string AnimalId);
FarmAnimal();
~FarmAnimal();
};
One of the first questions we must ask ourselves when beginning to write a program is, what is the data object and what variables/member elements is it to contain? Each object member should have an ID to distinguish it from other members so as to identify it when searching and to assist in avoiding duplicate members. The range of other members which I require for my program are declared above. I also include a Soldflag variable to indicate the presence/absence of sales data. This provides the oppurtunity to check for the presence/absence of sales data most easily if desired. For the setting accessor functions I am using default value functions. This means that objects on creation can be initialized without having to explicitly pass in data. Initializing objects on instantiation is a practice which prevents having null valued objects in the program. Using this practice also means that the programmer can alternate between filling members with generic/initialization data or actual data easily. Although exceptions are not included in this program I do include methods for preventing the input of invalid data or incorrectly formatted data. These should be made part of the class object and safeguard against the entry of invalid data into the container class. Overloaded operator functions present are useful and easy to implement.
class Counter
{
private:
int *Count;
public:
Counter();
~Counter();
Counter(Counter& RHS); // Copy constructor should always be included
// where member data is later being defined
// on the free store.
void SetCounter(int sCount);
int GetCounter(void);
Counter& operator++(); // Overload these operators for ease of use of
Counter operator++(int theflag); // Counter object.
Counter& operator--();
};
Dedicating a class to for the counter object gives an extra layer of access protection for the variable throughout the program. The object can be incremented and decremented easily courtesy of the inclusion of operator overloaded methods. It should be pointed out that the counter class keeps track of actual members and is not incremented when the container is initialized with generic/initialization data( that is zeros for int or float or for strings.. 'unfilled')
class AnimalContainer
{
public:
AnimalContainer(int theSize); // facilitates user to set size of container in constructor.
AnimalContainer(AnimalContainer& RHS); // We may want to create a copy of the container
// before user makes any changes to it. The option
// would be there to use it like an undo button and
// could provide an important layer of insurance
// for the user.
virtual ~AnimalContainer(); // Destructor in base class should always be declared
// virtual.
void Fillcontainer(Counter& CountFilled); // This function has been very useful for
// testing purposes
int VerifyCount(Counter& CountFilled); // Explicit check to ensure counter value
// is equal to number of inputted members.
bool IfMaxReached(Counter& CountFilled); // User should be informed if they are close
// to or at full capacity.
void DisplayMember(int Offset);
int search(FarmAnimal *temps,Counter& CountFilled); // Search should be overloaded to
//find and display a member but
int search(FarmAnimal *temps,bool *ifpresent,Counter& ContFiled);// also to check for presence
// without displaying, as a
// safeguarding mechanism in
// preventing duplicate entries.
// can be called from CreateNewMember().
int CreateNewMember(FarmAnimal *tempc,Counter& CountFilled);
int DeleteMember(FarmAnimal *tempc,Counter& Countfilled);
int Amend(FarmAnimal* tempc,Counter& CountFilled);
void InsertNewMember(FarmAnimal *temps,Counter& CountFilled);
int DisplayContainerMembers(Counter& CountFilled);
FarmAnimal& operator[](int offset)
{
return container[offset]; // Declare a function inline where appropriate.
}
AnimalContainer& operator=(AnimalContainer& RHS);
protected:
FarmAnimal *container; // Intended to use as pointer to array of objects on the freestore
int Size; // representing a database of records. User selects the size so
// strucure can grow or shrink as required. This represents the DMA.
};
This is the container class. The constructor for the class takes an integer size and when implemented sets aside enough space on the freestore for an array of member objects of type FarmAnimal. This demonstrates a has-a relationship and is an example of containment and aggregation in the programming. The pointer to FarmAnimal object becomes a pointer to an array on the freestore, the size of which is decided by the user. The copy constructor must always be present where memory is being created on the freestore in the constructor and so it is present here.
Most methods in this class include a counter variable passed by reference using a reference. This is because any change made to the counter variable inside the method must be registered outside of the method also. A temporary Farmanimal object is passed to several of the functions by reference using a pointer. This is useful for passing the object between methods without having to make a copy of the object and to preserve its value outside of each method. For example the create method will read in values for the temp object before passing it to an overloaded search method(function within a function) to check for presence ensuring that the member is not already present in the database before passing it to insert. This process ensures any change made to the temp object is preserved before being passed to insert.
The overloaded search method is necessary since we will want we will want to display values if a member is found in one instance, and only to indicate presence/absence in the other instance. The latter is safeguarding mechanism, as mentioned, before deletion or insertion or when a member is being amended/updated. A 'presence variable' is passed by reference using a pointer to one of the overloaded search functions as it's value will be needed to be preserved for an outer function.
The VerifyCount method is used regularly throughout the program to ensure that the value of the counter variable is indeed equal to the number of created or saved members. In the software development stage I model the container as an actor in the system calling on VerifyCount at various stages as a safeguarding mechanism. The same can be described for the IfMaxreached method. This notifies the user if they are at or nearing full capacity in the container and to delete members or make more room in the container which can be easily controlled by the user when launching the program. At the launch of the program each time the user is asked what size they would like the container to be so the size is always dictated by the user. This is the essence of dynamic memory allocation, ie. the container can grow or shrink in accordance with the users needs.
class Fileprocesses: public AnimalContainer // Seperate class for file support inherited
//from container class so as to have access
{ //to container structure.
public:
Fileprocesses(int Size); // Size of container must percolate upwards to base class.
~Fileprocesses();
int LoadFromFile(Counter& CountFilled); // All information added to structure must be saved for
int SaveToFile(Counter& CountFilled); // later access via the load function.
int PrintAsReport(Counter& CountFilled); // Making use of a second and seperate file so as
// structure data can be printed as a presentable
}; // report.
Here I create a new object for file streaming capability which must be inherited from the container class as it must have indirect access to the container and container data. PrintAsReport ie. print to file as report uses a different file to send data to than SaveToFile and so operates a little differently. When using PrintToFile, the data must formatted for output to be presentable to the farmer.
class ProcessClass: public Fileprocesses
{
public:
ProcessClass(int Size); // Structure size selected by user percolates upwards
// to container class.
~ProcessClass();
int TotalCostbySupplierName(Counter& CountFilled); // Varied set of options for accounting.
int TotalCostbyDateSold(Counter& CountFilled);
int TotalCostsInYear(Counter& CountFilled);
float TotalRevenuebySupplierName(Counter& CountFilled);
float TotalRevenuebyDateSold(Counter& CountFilled);
float TotalRevenueInYear(Counter& CountFilled);
float TotalProfitbySupplierName(Counter& CountFilled);
float TotalProfitbyDateSold(Counter& CountFilled);
float TotalProfitInYear(Counter& CountFilled);
};
The ProcessClass has financial accounting functionality and is inherited from the file processes class and so it inherits all the attributes and functionality of both the Fileprocesses class and the Container class. Size is passed as parameter to the constructor and percolates upwards through the classes to base container class and dictates the size of the container. The specialized financial accounting functions calculate either costs, revenue or profit based on a particular parameter. For example the TotalCostbySupplierName function delivers total costs accrued by farm bovines that were supplied by a parictlar supplier. The TotalCostbyDateSold function delivers total costs accrued by farm bovines which were sold on a particular date and so on.